package scc.com.printer;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.gprinter.aidl.GpService;
import com.gprinter.command.EscCommand;
import com.gprinter.command.GpCom;
import com.gprinter.command.GpUtils;
import com.gprinter.command.LabelCommand;
import com.gprinter.io.GpDevice;
import com.gprinter.io.PortParameters;
import com.gprinter.service.GpPrintService;

import java.util.Vector;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
//import scc.com.printer.bean.BluetoothParamBean;

public class MainActivity extends AppCompatActivity {
    private GpService mGpService = null;
    private int SCAN_PRINTER_ADVICE = 1001;
    private static final int REQUEST_PRINT_RECEIPT = 0xfc;
    private static final int MAIN_QUERY_PRINTER_STATUS = 0xfe;
    private PrinterServiceConnection conn = null;
    @InjectView(R.id.btn_get_printer_status)
    Button btnGetPrinterStatus;
    @InjectView(R.id.activity_main_tv_printer_con_status)
    TextView tvPrinterConStatus;
    @InjectView(R.id.activity_main_tv_printer_status)
    TextView tvPrinterStatus;
    @InjectView(R.id.btn_conn)
    Button btnConnect;
    @InjectView(R.id.activity_main_btn_test)
    Button btnTest;
    @InjectView(R.id.btn_get_printer_conn_status)
    Button btnGetPrinterConnStatus;
    @InjectView(R.id.tv_name)
    TextView tvName;
    @InjectView(R.id.tv_address)
    TextView tvAddress;
    private int mPrinterIndex = 0;
    private int CONNECT_TYPE = 4;//蓝牙连接
    private String TAG = "PPPPP";
    private Intent intent;

    class PrinterServiceConnection implements ServiceConnection {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("ServiceConnection", "onServiceDisconnected() called");
            mGpService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Toast.makeText(MainActivity.this, "onServiceConnected", Toast.LENGTH_SHORT).show();
            Log.i("ServiceConnection", "onServiceConnected() called");
            mGpService = GpService.Stub.asInterface(service);

        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        connection();
        registerBrocaster();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
        unregisterReceiver(mBroadcastReceiver);
        unregisterReceiver(PrinterStatusBroadcastReceiver);
    }

    private void registerBrocaster() {
        // 注册实时状态查询广播
        registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_DEVICE_REAL_STATUS));
        /**
         * 票据模式下，可注册该广播，在需要打印内容的最后加入addQueryPrinterStatus()，在打印完成后会接收到
         * action为GpCom.ACTION_DEVICE_STATUS的广播，特别用于连续打印，
         * 可参照该sample中的sendReceiptWithResponse方法与广播中的处理
         **/
        registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_RECEIPT_RESPONSE));
        /**
         * 标签模式下，可注册该广播，在需要打印内容的最后加入addQueryPrinterStatus(RESPONSE_MODE mode)
         * ，在打印完成后会接收到，action为GpCom.ACTION_LABEL_RESPONSE的广播，特别用于连续打印，
         * 可参照该sample中的sendLabelWithResponse方法与广播中的处理
         **/
        registerReceiver(mBroadcastReceiver, new IntentFilter(GpCom.ACTION_LABEL_RESPONSE));

        IntentFilter filter = new IntentFilter();
        filter.addAction(GpCom.ACTION_CONNECT_STATUS);
        this.registerReceiver(PrinterStatusBroadcastReceiver, filter);
    }

    @OnClick({R.id.btn_conn, R.id.activity_main_btn_test, R.id.btn_get_printer_status,
            R.id.btn_dis_conn, R.id.btn_get_printer_conn_status})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_conn:
                Intent intent = new Intent(this, BluetoothDeviceList.class);
                startActivityForResult(intent, SCAN_PRINTER_ADVICE);
                break;
            case R.id.btn_dis_conn:
                try {
                    int printerConnStatus = getPrinterConnStatus();
                    if (printerConnStatus != GpDevice.STATE_CONNECTED) {
                        Toast.makeText(this, "设备尚未连接", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    mGpService.closePort(mPrinterIndex);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.activity_main_btn_test:
                printReceiptClicked();
                //           sendReceipt(mPrinterIndex);

                break;
            case R.id.btn_get_printer_status:
                getPrinterStatus();
                break;
            case R.id.btn_get_printer_conn_status:
                getPrinterConnStatus();
                break;
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SCAN_PRINTER_ADVICE) {
            if (resultCode == RESULT_OK) {
                int type = data.getIntExtra("type", 4);
                String address = data.getStringExtra("name-address");
                PortParameters portParameters = new PortParameters();
                portParameters.setPortType(type);
                portParameters.setBluetoothAddr(address);
//                PortParameters bluetoothParamBean =
//                        (PortParameters) data.getSerializableExtra("bluetoothParamBean");
                connectToDevice(portParameters);
            }
        }
    }


    private void connection() {
        conn = new PrinterServiceConnection();
        intent = new Intent(this, GpPrintService.class);
        bindService(intent, conn, Context.BIND_AUTO_CREATE); // bindService
    }

    void connectToDevice(final PortParameters bean) {
        final String name = bean.getBluetoothAddr().split("-")[0];
        final String address = bean.getBluetoothAddr().split("-")[1];
        try {
            mGpService.closePort(mPrinterIndex);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
                int rel = 0;
                try {
                    /**
                     * mPrinterIndex 连接打印机序列号 0,1,2 最多连接三个打印机
                     *
                     * CONNECT_TYPE 4:连接类型 蓝牙连接是4
                     */
                    rel = mGpService.openPort(mPrinterIndex, CONNECT_TYPE, address, 0);
                    e.onNext(rel);
                } catch (RemoteException re) {
                    re.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
//                        switch (integer) {
//                            case GpDevice.STATE_LISTEN:
//                                break;
//                            case GpDevice.STATE_NONE://连接断开
//                                Log.d(TAG, "STATE_NONE: ");
//                                break;
//                            case GpDevice.STATE_CONNECTING://连接中
//                                Log.d(TAG, "STATE_CONNECTING: ");
//                                break;
//                            case GpDevice.STATE_CONNECTED://已连接
//                                Log.d(TAG, "STATE_CONNECTED: ");
//                                break;
//                            case GpDevice.STATE_INVALID_PRINTER: // 无效的打印机
//                                Log.d(TAG, "STATE_INVALID_PRINTER: ");
//                                break;
//                            case GpDevice.STATE_VALID_PRINTER://有效的打印机
//                                Log.d(TAG, "STATE_VALID_PRINTER: ");
//                                break;
//                        }

                        GpCom.ERROR_CODE r = GpCom.ERROR_CODE.values()[integer];
                        Log.e(TAG, "result :" + String.valueOf(r));
                        if (r != GpCom.ERROR_CODE.SUCCESS) {
                            Toast.makeText(MainActivity.this, "aaa", Toast.LENGTH_SHORT).show();
                            if (r == GpCom.ERROR_CODE.DEVICE_ALREADY_OPEN) {
                                Toast.makeText(MainActivity.this, "bbb", Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            tvName.setText(name);
                            tvAddress.setText(address);
                        }
                    }
                });
    }


    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d("TAG", action);
            // GpCom.ACTION_DEVICE_REAL_STATUS 为广播的IntentFilter
            if (action.equals(GpCom.ACTION_DEVICE_REAL_STATUS)) {
                /**
                 * STATE_NO_ERR = 0; // 正常
                 STATE_OFFLINE = 0x1; // 脱机
                 STATE_PAPER_ERR = 0x2; 缺纸
                 STATE_COVER_OPEN = 0x4; 开盖
                 STATE_ERR_OCCURS = 0x8; 过热 错误
                 */

                // 业务逻辑的请求码，对应哪里查询做什么操作
                int requestCode = intent.getIntExtra(GpCom.EXTRA_PRINTER_REQUEST_CODE, -1);
                // 判断请求码，是则进行业务操作
                if (requestCode == MAIN_QUERY_PRINTER_STATUS) {

                    int status = intent.getIntExtra(GpCom.EXTRA_PRINTER_REAL_STATUS, 16);
                    String str;
                    if (status == GpCom.STATE_NO_ERR) {
                        str = "打印机正常";
                    } else {
                        str = "打印机 ";
                        if ((byte) (status & GpCom.STATE_OFFLINE) > 0) {
                            str += "脱机";
                        }
                        if ((byte) (status & GpCom.STATE_PAPER_ERR) > 0) {
                            str += "缺纸";
                        }
                        if ((byte) (status & GpCom.STATE_COVER_OPEN) > 0) {
                            str += "打印机开盖";//TODO 开盖也提示缺纸
                        }
                        if ((byte) (status & GpCom.STATE_ERR_OCCURS) > 0) {
                            str += "打印机出错";
                        }
                        if ((byte) (status & GpCom.STATE_TIMES_OUT) > 0) {
                            str += "查询超时";
                        }
                    }
                    tvPrinterStatus.setText(str);
                } else if (requestCode == REQUEST_PRINT_RECEIPT) {
                    int status = intent.getIntExtra(GpCom.EXTRA_PRINTER_REAL_STATUS, 16);
                    if (status == GpCom.STATE_NO_ERR) {
                        sendReceipt(mPrinterIndex);
                    } else {
                        Toast.makeText(MainActivity.this, "query printer status error", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    };
    private BroadcastReceiver PrinterStatusBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String connectStatus = "";
            if (GpCom.ACTION_CONNECT_STATUS.equals(intent.getAction())) {
                int type = intent.getIntExtra(GpPrintService.CONNECT_STATUS, 0);
                int id = intent.getIntExtra(GpPrintService.PRINTER_ID, 0);
                Log.d(TAG, "connect status " + type);
                if (type == GpDevice.STATE_CONNECTING) {
                    connectStatus = "连接中";
                    Log.d(TAG, "onReceive: STATE_CONNECTING");
                    Toast.makeText(context, "STATE_CONNECTING", Toast.LENGTH_SHORT).show();
                } else if (type == GpDevice.STATE_NONE) {
                    connectStatus = "连接断开";
                    Log.d(TAG, "onReceive: STATE_NONE");
                    Toast.makeText(context, "STATE_NONE", Toast.LENGTH_SHORT).show();
                } else if (type == GpDevice.STATE_VALID_PRINTER) {
                    connectStatus = "有效连接";
                    Log.d(TAG, "onReceive: STATE_VALID_PRINTER");
                    Toast.makeText(context, "STATE_VALID_PRINTER", Toast.LENGTH_SHORT).show();

                } else if (type == GpDevice.STATE_INVALID_PRINTER) {
                    connectStatus = "无效连接";
                    Log.d(TAG, "onReceive: STATE_INVALID_PRINTER");
                    Toast.makeText(context, "STATE_INVALID_PRINTER", Toast.LENGTH_SHORT).show();

                } else if (type == GpDevice.STATE_CONNECTED) {
                    connectStatus = "已连接";
                    Log.d(TAG, "onReceive: STATE_CONNECTED");
                    Toast.makeText(context, "STATE_CONNECTED", Toast.LENGTH_SHORT).show();
                }

                tvPrinterConStatus.setText(connectStatus);
            }
        }
    };


    /**
     * 查询打印机的状态
     */
    public void getPrinterStatus() {
        if (mGpService == null) return;
        try {
            mGpService.queryPrinterStatus(mPrinterIndex, 500, MAIN_QUERY_PRINTER_STATUS);
        } catch (RemoteException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * 查看打印机连接状态
     */
    public int getPrinterConnStatus() {
        try {
            int printerConnectStatus = mGpService.getPrinterConnectStatus(0);
            String str = "unknow";
            switch (printerConnectStatus) {
                case GpDevice.STATE_NONE:// 连接断开
                    str = "连接断开";
                    break;
                case GpDevice.STATE_LISTEN:// 连接监听
                    str = "连接监听";
                    break;
                case GpDevice.STATE_CONNECTING:// 连接中
                    str = "连接中";
                    break;
                case GpDevice.STATE_CONNECTED:// 已连接
                    str = "已连接";
                    break;
                case GpDevice.STATE_INVALID_PRINTER://无效链接
                    str = "无效链接";
                    break;
                case GpDevice.STATE_VALID_PRINTER://有效连接
                    str = "有效连接";
                    break;
            }
//            tvPrinterConStatus.setText(str);
            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
            return printerConnectStatus;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return -1;
    }

    public void printReceiptClicked() {
        if (mGpService == null) return;
        try {
            int type = mGpService.getPrinterCommandType(mPrinterIndex);
            if (type == GpCom.ESC_COMMAND) {
                mGpService.queryPrinterStatus(mPrinterIndex, 1000, REQUEST_PRINT_RECEIPT);
            } else {
                Toast.makeText(this, "Printer is not receipt mode", Toast.LENGTH_SHORT).show();
            }
        } catch (RemoteException e1) {
            e1.printStackTrace();
        }
    }

    void sendReceipt(int mPrinterIndex) {

        EscCommand esc = new EscCommand();
        esc.addInitializePrinter();
        esc.addPrintAndFeedLines((byte) 2);//打印并走纸三行
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);// 设置打印居中
        esc.addSelectPrintModes(
                EscCommand.FONT.FONTA,
                EscCommand.ENABLE.OFF,
                EscCommand.ENABLE.ON,
                EscCommand.ENABLE.ON,
                EscCommand.ENABLE.OFF);// 设置为倍高倍宽
        esc.addText("违章停车单\n"); // 打印文字
        esc.addPrintAndLineFeed();

		/* 打印文字 */
        esc.addSelectPrintModes(
                EscCommand.FONT.FONTA,
                EscCommand.ENABLE.OFF,
                EscCommand.ENABLE.OFF,
                EscCommand.ENABLE.OFF,
                EscCommand.ENABLE.OFF);// 取消倍高倍宽
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);// 设置打印左对齐
        esc.addText("           编号："); // 打印文字
        esc.addText("100000001001001\n"); // 打印文字

		/* 打印繁体中文 需要打印机支持繁体字库 */
        String message = "    该车辆于2017-7-11日号违反了《道路交通安全法》第56条规定，请持本通知书到北京交通大厦\n";
        // esc.addText(message,"BIG5");
        esc.addText(message, "GB2312");
//        esc.addPrintAndLineFeed();
//        /* 绝对位置 具体详细信息请查看GP58编程手册 */
        esc.addText("便宜");
        esc.addSetHorAndVerMotionUnits((byte) 7, (byte) 0);
        esc.addSetAbsolutePrintPosition((short) 6);
        esc.addText("划算");
        esc.addSetAbsolutePrintPosition((short) 10);
        esc.addText("好吃");
        esc.addPrintAndLineFeed();
//
//		/* 打印图片 */
////        esc.addText("Print bitmap!\n"); // 打印文字
////        Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.gprinter);
////        esc.addRastBitImage(b, 384, 0); // 打印图片
//
//		/* 打印一维条码 */
////        esc.addText("Print code128\n"); // 打印文字
//        esc.addSelectPrintingPositionForHRICharacters(EscCommand.HRI_POSITION.BELOW);//
//        // 设置条码可识别字符位置在条码下方
//        esc.addSetBarcodeHeight((byte) 60); // 设置条码高度为60点
//        esc.addSetBarcodeWidth((byte) 1); // 设置条码单元宽度为1
//        esc.addCODE128(esc.genCodeB("yangqing")); // 打印Code128码
//        esc.addPrintAndLineFeed();
//
//		/*
//         * QRCode命令打印 此命令只在支持QRCode命令打印的机型才能使用。 在不支持二维码指令打印的机型上，则需要发送二维条码图片
//		 */
        esc.addText("Print QRcode\n"); // 打印文字
        esc.addSelectErrorCorrectionLevelForQRCode((byte) 0x31); // 设置纠错等级
        esc.addSelectSizeOfModuleForQRCode((byte)6);// 设置qrcode模块大小
        esc.addStoreQRCodeData("http://www.baidu.com");// 设置qrcode内容
        esc.addPrintQRCode();// 打印QRCode
        esc.addPrintAndLineFeed();
//
//		/* 打印文字 */
//        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);// 设置打印左对齐
//        esc.addText("Completed!\r\n"); // 打印结束
        // 开钱箱
        esc.addGeneratePlus(LabelCommand.FOOT.F5, (byte) 255, (byte) 255);
//        esc.addPrintAndFeedLines((byte) 8);

        Vector<Byte> datas = esc.getCommand(); // 发送数据
        byte[] bytes = GpUtils.ByteTo_byte(datas);
        String sss = Base64.encodeToString(bytes, Base64.DEFAULT);
        int rs;
        try {

            rs = mGpService.sendEscCommand(mPrinterIndex, sss);
            GpCom.ERROR_CODE r = GpCom.ERROR_CODE.values()[rs];
            if (r != GpCom.ERROR_CODE.SUCCESS) {
                Toast.makeText(getApplicationContext(), GpCom.getErrorText(r), Toast.LENGTH_SHORT).show();
            }
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}